//package com.zhz.mall.common.util.feign;
//
//import cn.hutool.core.util.ArrayUtil;
//import com.netflix.hystrix.exception.HystrixRuntimeException;
//import com.ygp.base.utils.YgpJsonUtils;
//import com.ygp.base.web.interceptor.FeignFallbackAspect;
//import com.ygp.common.utils.Result;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.core.Ordered;
//import org.springframework.util.ClassUtils;
//
//import java.util.Objects;
//
//
//
///**
// * GlobalFeignFallback
// * <p>
// * 为 feign 提供全局默认的 fallback 处理，将 feign 调用失败的异常信息封装成 {@link Result} 返回，而不是直接向上抛出异常，
// * 用户获取到 result 结果之后，应该判断 result 是否成功，而不是直接获取 data
// *
// * @author zhangjiawei@sanyygp.com
// * @version 1.0
// * @date 2020/11/21 9:40
// *
// * @see FeignFallbackAspect
// */
//@Slf4j
//@Aspect
//public class GlobalFeignFallback implements Ordered {
//
//    @Pointcut("@within(org.springframework.cloud.openfeign.FeignClient)")
//    public void feignClient(){}
//
//
//    @Pointcut("execution(com.ygp.common.utils.Result *.*(..))")
//    public void resultReturnType(){}
//
//
//
//    @Around("feignClient() && resultReturnType()")
//    public Result doFallback(ProceedingJoinPoint joinPoint) {
//        long start = System.currentTimeMillis();
//        long end;
//        try {
//            Result result = (Result) joinPoint.proceed();
//            if (Objects.nonNull(result) && result.isFailed()) {
//                end = System.currentTimeMillis();
//                log.warn("feign 接口[{}]执行状态异常: {}, 接口参数: {}, 请求耗时: {}",
//                        getMethodName(joinPoint), result, getParams(joinPoint), (end - start));
//            }
//            return result;
//        } catch (Throwable cause) {
//            end = System.currentTimeMillis();
//            cause = unwrapSuperCause(cause, HystrixRuntimeException.class);
//            log.error("feign 接口[{}]调用失败: {}, 接口参数: {}, 请求耗时: {}",
//                    getMethodName(joinPoint), cause.getMessage(), getParams(joinPoint), (end - start), cause);
//            return new FeignFallbackResult(cause.getMessage(), cause, start, end);
//        }
//    }
//
//
//    /**
//     * 解析方法名称
//     */
//    private String getMethodName(ProceedingJoinPoint joinPoint) {
//        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//        return ClassUtils.getQualifiedMethodName(methodSignature.getMethod());
//    }
//
//
//    /**
//     * 解析方法参数
//     */
//    private String getParams(ProceedingJoinPoint joinPoint) {
//        Object[] args = joinPoint.getArgs();
//        String params = ArrayUtil.isNotEmpty(args) ? YgpJsonUtils.toJson(args) : "[]";
//        if (params.length() > 1000)  {
//            params = params.substring(0, 1000) + "...";
//        }
//        return params;
//    }
//
//
//    @Override
//    public int getOrder() {
//        return Ordered.HIGHEST_PRECEDENCE + 10;
//    }
//
//
//
//
//    /**
//     * 当目标异常为指定异常类型，且父异常不为空时，返回父异常，否则返回原异常
//     */
//    private static Throwable unwrapSuperCause(Throwable cause, Class<? extends Throwable> targetType) {
//        if (targetType.isInstance(cause) && Objects.nonNull(cause.getCause())) {
//            return cause.getCause();
//        }
//        return cause;
//    }
//
//}
